package hotel.callback.oversea.task;

import hotel.callback.oversea.config.service.RedisService;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.constant.MeituanConstants;
import hotel.base.oversea.constant.enums.MtGoodsEnums;
import hotel.base.oversea.utils.DateUtil;
import hotel.base.oversea.utils.GsonUtils;
import hotel.base.oversea.utils.Result;
import hotel.base.oversea.utils.StringUtil;
import hotel.base.oversea.vo.BatchPushRoomDatasVo;
import hotel.base.oversea.vo.RoomDataEntityVO;
import hotel.base.oversea.vo.RoomPriceVo;
import hotel.base.oversea.vo.meituan.response.goods.MtHotelGoodsPriceBaseDetailVo;
import hotel.base.oversea.vo.meituan.response.goods.MtHotelGoodsPriceBaseVo;
import hotel.callback.oversea.service.MtHotelCheckGoodsPriceService;
import hotel.callback.oversea.service.MtHotelGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;


@Slf4j
@Component
public class MeituanPartTimeQueryPriceTask {
    private String timestamp = "mcohgdt"+String.valueOf(System.currentTimeMillis());
    @Autowired
    private MtHotelCheckGoodsPriceService mtHotelCheckGoodsPriceService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MtHotelGoodsService mtHotelGoodsService;
    @Autowired
    private RestTemplate restTemplate;
    private void setTimestamp(String timestamp){
        this.timestamp = timestamp;
    }

    @Async("threadPoolPr")
    public void executeCheckOneHotelGoods(String sourName,List<Long> thisHotelIdList,String timestamp,Integer days){
        log.info("sourceName={}MeituanSaveApiLogTask {} >>>>>>>>> 异步线程 节点定时器查询价格task  开始执行时间：{}",sourName,timestamp, DateUtil.getNowTime());
        setTimestamp(timestamp);

        //主动查询价格
        queryRoomPriceByOneHotelIdV2(sourName,thisHotelIdList,days);

        //log.info("sourceName={}MeituanSaveApiLogTask {} >>>>>>>>> 异步线程 节点定时器查询价格task  执行结束时间：{}",sourName,timestamp, DateUtil.getNowTime());
    }
    private void queryRoomPriceByOneHotelIdV2(String sourceName,List<Long> thisHotelIdList,Integer difDays){
        //log.info("sourceName={}进入 queryRoomPriceByOneHotelIdV2 hotelId={}", sourceName,GsonUtils.GsonString(thisHotelIdList));
        Date nowDate = new Date();
        //Integer difDays = mtHotelGoodsService.getDaysCommonBaseSet();
        String endDate = DateUtil.formatDate(DateUtil.addDay(nowDate,difDays),"yyyy-MM-dd");
        if(null != redisService.get("query_status_time_days_endDate")){
            endDate = (String)redisService.get("query_status_time_days_endDate");
        }
        String hourStr = DateUtil.formatDate(nowDate,"HH");
        String todayOrYest = DateUtil.formatDate(nowDate,"yyyy-MM-dd");
        if("00,01,02,03,04,05,06".contains(hourStr)){
            todayOrYest = DateUtil.formatDate(DateUtil.addDay(nowDate,-1),"yyyy-MM-dd");
        }
        String startDatePrice = DateUtil.formatDate(nowDate,"yyyy-MM-dd");
        String nowStr = DateUtil.formatDate(nowDate,"yyyy-MM-dd HH");
        if(Integer.valueOf(nowStr.split(" ")[1])<6){
            startDatePrice = DateUtil.getFontsDay(startDatePrice);//往前推一天查询，涉及隔夜价格问题
        }

        //3、产品价格日历查询用酒店id，因为产品id查询限制10个一个酒店可很多个产品（根据时间段数据返回）调用价格日历接口，参数美团ids(产品id每次十个)，上送一个酒店调用上游接口获取所有产品价格日历信息//调用上游接口时不可即时保持到产品价格表，因为下面的代码判断价格是根据库表内容的
        //当前酒店所有产品涉及所有日期价格变动集合   key = 产品id  value = 该产品id涉及变动的价格日期信息集合 --》 Map<String,Map<String,MtHotelGoodsPriceBaseDetailVo>>

        /*List<Long> thisHotelIdList = new ArrayList<>();
        thisHotelIdList.add(Long.valueOf(hotelId));*/
        Result result = mtHotelGoodsService.getMtHotelGoodsPriceNotSave(thisHotelIdList,null,startDatePrice,endDate);
        //log.info("sourceName={}MeituanPartTimeQueryPriceTask thisHotelIdList={}，result={}",sourceName,GsonUtils.GsonString(thisHotelIdList),GsonUtils.GsonString(result));
        if(result.getCode() == CommonConstants.SUCCESS && null != result.getData()){//返回某一个酒店所有产品价格信息
            List<MtHotelGoodsPriceBaseVo> mtHotelGoodsListAboutPriceDataVo = (List<MtHotelGoodsPriceBaseVo>)result.getData();

            if(null != mtHotelGoodsListAboutPriceDataVo && mtHotelGoodsListAboutPriceDataVo.size()>0){
                //log.info("sourceName={}构建酒店数据前：{}", sourceName,GsonUtils.GsonString(mtHotelGoodsListAboutPriceDataVo));
                Map<Integer,List<MtHotelGoodsPriceBaseVo>> manyHotelGoodsMap = new HashMap<>();
                for(MtHotelGoodsPriceBaseVo oneGoodsAboutPriceListVo:mtHotelGoodsListAboutPriceDataVo){
                    Integer thisHotelId = oneGoodsAboutPriceListVo.getHotelId();
                    /*Boolean existSaleHotel = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_TO_PRICE_LIST,thisHotelId);
                    if(existSaleHotel){
                        log.info("sourceName={}MeituanPartTimeQueryPriceTask 不是上架酒店 thisHotelId={}",thisHotelId);
                        continue;
                    }*/
                    List<MtHotelGoodsPriceBaseVo> arr = manyHotelGoodsMap.get(thisHotelId);
                    if(arr==null || arr.size()==0){
                        arr = new ArrayList<>();
                    }
                    arr.add(oneGoodsAboutPriceListVo);
                    manyHotelGoodsMap.put(thisHotelId,arr);
                }
                for (Map.Entry oneHotel:manyHotelGoodsMap.entrySet()){
                    Integer thisHotelCompare = 0;
                    List<MtHotelGoodsPriceBaseVo> thisHotelGoodsList = (List<MtHotelGoodsPriceBaseVo>)oneHotel.getValue();
                    Integer thisHotelId = (Integer)oneHotel.getKey();
                    Long thisTimestamp = System.currentTimeMillis();
                    String thisTimestampApi = StringUtil.getTimestampRandom(thisTimestamp)+String.valueOf(thisHotelId).substring(0,4)+String.valueOf(11);
                    log.info("sourceName={}queryRoomPriceByOneHotelId价格酒店={}",sourceName,thisHotelId);
                    Map<Integer,Integer> valiSaleAllGoodsMap = new HashMap();//key = goodsId,vallue=goodsId  组装集合放置所有校验后有效的产品（因为存在某产品无价格变化但有状态变化需处理）
                    Map<String,Map<String, MtHotelGoodsPriceBaseDetailVo>> allChangeGoodsAboutDatePriceMap = new HashMap<>();
                    for(MtHotelGoodsPriceBaseVo oneGoodsAboutPriceListVo:thisHotelGoodsList){
                        //遍历多个产品
                        Integer goodsId = oneGoodsAboutPriceListVo.getGoodsId();//当前产品id

                        //判断该产品是否为我们的上架产品，是才需要查询比对价格
                        String existSale = null;//(String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+key);

                        existSale = (String)redisService.hmGet(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE,thisHotelId+"_"+goodsId);
                        if(!ObjectUtils.isEmpty(existSale)){
                            //log.info("sourceName={}MeituanPartTimeQueryPriceTask 进入第二版 判断上架产品：thisGoodsId={},existSale={}",sourceName,goodsId,existSale);
                        }else{
                            existSale = (String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+thisHotelId+"_"+goodsId);
                            //log.info("sourceName={}MeituanPartTimeQueryPriceTask 进入第一版 判断上架产品：thisGoodsId={},existSale={}",sourceName,goodsId,existSale);
                        }

                        if(null != existSale){
                            //log.info("sourceName={}MeituanPartTimeQueryPriceTask existSale={}",sourceName,existSale);
                            //log.info("sourceName={}主动查询-美团接口-校验酒店产品 {}  hotel={} queryRoomPriceByOneHotelId循环产品当前该产品为售卖房型 existSale  into  hotel_goodsId={}",timestamp,hotelId,key);

                            //key = 产品id  + 日期 ， value = 价格信息 --》 Map<String,MtHotelGoodsPriceBaseDetailVo>
                            Integer fromJob = 10;
                            if("VIP".equals(sourceName)){
                                fromJob = 50;
                            }else if("NORMAL".equals(sourceName)){
                                fromJob = 60;
                            }
                            Map<String, MtHotelGoodsPriceBaseDetailVo> oneGoodsChangeAboutDatePriceMap = mtHotelCheckGoodsPriceService.checkOneGoodsArrayDateChange(todayOrYest,oneGoodsAboutPriceListVo.getPriceModels(),thisHotelId,goodsId,hourStr,result,thisTimestampApi,fromJob);//10 独立价格定时器 11RpOne定时器 12 异步推送  50 优势酒店价格定时器  60 普通酒店价格定时器
                            if(!ObjectUtils.isEmpty(oneGoodsChangeAboutDatePriceMap)){
                                //log.info("sourceName={}主动查询-美团接口-校验酒店产品 {} 一个产品一组日期价格结束校对有变化 hotel_goodsId={}, oneGoodsChangeAboutDatePriceMap= {}",timestamp,key,GsonUtils.GsonString(oneGoodsChangeAboutDatePriceMap));
                                if(oneGoodsChangeAboutDatePriceMap.size()>0){//当前该产品的日期价格集合存在变更时 加入所有产品变更map
                                    allChangeGoodsAboutDatePriceMap.put(String.valueOf(goodsId),oneGoodsChangeAboutDatePriceMap);
                                    //log.info("sourceName={}主动查询-美团接口-校验酒店产品 {} getChangeMonthGoodsIdsByOneHotelId hotel_goodsId={},一个产品一组日期价格结束校对存在变化追加 allChangeGoodsAboutDatePriceMap= {}",timestamp,key,GsonUtils.GsonString(allChangeGoodsAboutDatePriceMap));
                                    valiSaleAllGoodsMap.put(goodsId,goodsId);
                                }
                            }else{
                                //一样，没有变化
                                log.info("sourceName={}oneGoodsChangeAboutDatePriceMap 为空 该产品没有产生变化日期价格goodsId={}",sourceName,goodsId);
                            }
                        }
                    }
                    int size = allChangeGoodsAboutDatePriceMap == null?0:allChangeGoodsAboutDatePriceMap.size();
                    if(size>0){
                        //log.info("sourceName={}该酒店存在价格需要推送酒店={},{}",sourceName,thisHotelId,timestamp);
                        log.info("sourceName={}///////////////////////主动查询-美团接口-校验酒店产品 {} 存在数据完成该酒店所有产品所有日期价格校对hotelId={},allChangeGoodsAboutDatePriceMap={},当前线程 结束时间 {}",sourceName,timestamp,thisHotelId,allChangeGoodsAboutDatePriceMap, DateUtil.getCurrTime());

                        //version 20200828 构建携程接口参数，保存变化的数据到缓存队列，
                        buildPriceChangeDataToSwitchsRedis(sourceName,String.valueOf(thisHotelId),valiSaleAllGoodsMap,allChangeGoodsAboutDatePriceMap, MtGoodsEnums.goodsChangeSource.PULL_PRICE.getCode(),thisHotelCompare,thisTimestampApi);//allChangeGoodsAboutStatusMap);

                    }else{
                        log.info("sourceName={}该酒店没有价格需要推送酒店={},{}",sourceName,thisHotelId,timestamp);
                    }
                }
            }

        }

    }

    /**
     * 变化的产品数据，重新构建数据vo 加入缓存队列
     * @param hotelId
     * @param valiSaleAllGoodsMap
     * @param allChangeGoodsAboutDatePriceMap
     */
    private void buildPriceChangeDataToSwitchsRedis(String sourceName,String hotelId,Map<Integer,Integer> valiSaleAllGoodsMap,
                                                    Map<String,Map<String, MtHotelGoodsPriceBaseDetailVo>> allChangeGoodsAboutDatePriceMap,
                                                    Integer source,Integer thisHotelCompare,String thisTimestampApi) {
        //log.info("sourceName={}{} 进入方法开始执行buildStatusChangeDataToSwitchsRedis,push到缓存队列存在变动的价格产品，" +
        //"主动变动价格入参有效产品集合为{},主动变动价格入参酒店为{},主动变动价格入参房态数据为{} ",timestamp,GsonUtils.GsonString(valiSaleAllGoodsMap),hotelId,GsonUtils.GsonString(allChangeGoodsAboutDatePriceMap));
        List<RoomDataEntityVO> oneHotelAboutAllChangeGoodsVoSwitchsApi = new ArrayList<>();//酒店vo-所有变化产品listVo，酒店vo所有变化了的产品信息
        BatchPushRoomDatasVo oneHotelVoSwitchsApi = null;//构建携程接口酒店vo

        for (Map.Entry entry:valiSaleAllGoodsMap.entrySet()){
            //遍历所有变化的产品
            String goodsId = String.valueOf(entry.getKey());

            //重构携程接口对象，构建一个产品vo，加入产品volist
            RoomDataEntityVO oneChangeGoodsSwitchsApi = new RoomDataEntityVO();
            oneChangeGoodsSwitchsApi.setGoodId(Integer.valueOf(goodsId));//当前产品id

            //构建接口数据结构：一个产品的价格 数据结构
            Map<String, MtHotelGoodsPriceBaseDetailVo> thisGoodsPriceDateList = allChangeGoodsAboutDatePriceMap.get(goodsId);//美团接口返回该产品发送变化的多组日期价格数据
            if(null != thisGoodsPriceDateList && thisGoodsPriceDateList.size()>0){
                List<RoomPriceVo> changeOneGoodsDatePriceListBuildSwitchsVo = new ArrayList<>();//重构携程接口对象，当前该产品的多组变化价格日期数据集合list
                for (Map.Entry thisGoodsOneChangePriceDate:thisGoodsPriceDateList.entrySet()){//遍历美团返回的每个产品的日期价格数据,每次一个日期的变化价格
                    //String thisMtGoodsId = thisGoodsOneChangePriceDate.getKey().toString().split("_")[0];
                    String thisMtGoodsOneChangeDate = thisGoodsOneChangePriceDate.getKey().toString().split("_")[1];
                    MtHotelGoodsPriceBaseDetailVo thisChangeDatePriceVo = (MtHotelGoodsPriceBaseDetailVo) thisGoodsOneChangePriceDate.getValue();
                    //构建当前产品的每个价格日期vo，加入list
                    RoomPriceVo thisGoodsThisOneDatePirceSwitchsVo = new RoomPriceVo();
                    thisGoodsThisOneDatePirceSwitchsVo.setSalePrice(thisChangeDatePriceVo.getSalePrice());
                    thisGoodsThisOneDatePirceSwitchsVo.setDate(thisMtGoodsOneChangeDate);
                    thisGoodsThisOneDatePirceSwitchsVo.setSubPrice(thisChangeDatePriceVo.getSubPrice());
                    changeOneGoodsDatePriceListBuildSwitchsVo.add(thisGoodsThisOneDatePirceSwitchsVo);
                }
                oneChangeGoodsSwitchsApi.setRoomPrices(changeOneGoodsDatePriceListBuildSwitchsVo);//当前产品所有多组价格日期集合
            }

            oneChangeGoodsSwitchsApi.setGoodInventory(1);//allValiSaleGoodsAboutValiInventoryMap.get(goodsId));//当前产品的库存（0或1表示未来一个月有或无）

            oneHotelAboutAllChangeGoodsVoSwitchsApi.add(oneChangeGoodsSwitchsApi);//追加入携程vo酒店所有变化产品集合中
        }
        //最终返回酒店vo
        if(null != oneHotelAboutAllChangeGoodsVoSwitchsApi && oneHotelAboutAllChangeGoodsVoSwitchsApi.size()>0){
            //log.info("sourceName={}oneHotelAboutAllChangeGoodsVoSwitchsApi={}", sourceName,GsonUtils.GsonString(oneHotelAboutAllChangeGoodsVoSwitchsApi));
            oneHotelVoSwitchsApi = new BatchPushRoomDatasVo();
            oneHotelVoSwitchsApi.setMtHotelId(Integer.valueOf(hotelId));
            oneHotelVoSwitchsApi.setCompare(thisHotelCompare);
            oneHotelVoSwitchsApi.setTimestamp(thisTimestampApi);
            oneHotelVoSwitchsApi.setRoomDataEntityList(oneHotelAboutAllChangeGoodsVoSwitchsApi);
            //log.info("sourceName={}{} push到缓存队列存在变动的价格产品，主动变动价格时间戳为{},主动变动价格酒店为{},主动变动价格推送数据为{} ",timestamp,thisTimestampApi,hotelId,GsonUtils.GsonString(oneHotelVoSwitchsApi));
            //oneHotelVoSwitchsApi json字符串 加入缓存队列中
            pushQueueRpPriceAndStatus(oneHotelVoSwitchsApi);
        }
    }

    public void pushQueueRpPriceAndStatus(BatchPushRoomDatasVo oneHotelVoSwitchsApi){

        //1、加入队列，推给携程
        redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL, GsonUtils.GsonString(oneHotelVoSwitchsApi));
    }

}
